#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>

struct node {
    int value;
    TAILQ_ENTRY(node) link;
    /*
    struct {
        struct node **prev;
        struct node *next;
    } link;
    */
};

TAILQ_HEAD(heads, node);

#if 0
struct heads {								 
	struct type *tqh_first;	/* first element */			 
	struct type **tqh_last;	/* addr of last next element */		 
}

#endif

#if 0 // TailQ define

/*
 * Tail queue declarations.
 */
#define	TAILQ_HEAD(name, type)						\
struct name {								\
	struct type *tqh_first;	/* first element */			\
	struct type **tqh_last;	/* addr of last next element */		\
}

#define	TAILQ_HEAD_INITIALIZER(head)					\
	{ NULL, &(head).tqh_first }

#define	TAILQ_ENTRY(type)						\
struct {								\
	struct type *tqe_next;	/* next element */			\
	struct type **tqe_prev;	/* address of previous next element */	\
}

/*
 * Tail queue functions.
 */
#define	TAILQ_EMPTY(head)	((head)->tqh_first == NULL)

#define	TAILQ_FIRST(head)	((head)->tqh_first)

#define	TAILQ_FOREACH(var, head, field)					\
	for ((var) = TAILQ_FIRST((head));				\
	    (var);							\
	    (var) = TAILQ_NEXT((var), field))

#define	TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
	for ((var) = TAILQ_LAST((head), headname);			\
	    (var);							\
	    (var) = TAILQ_PREV((var), headname, field))

#define	TAILQ_INIT(head) do {						\
	TAILQ_FIRST((head)) = NULL;					\
	(head)->tqh_last = &TAILQ_FIRST((head));			\
} while (0)

#define	TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
	if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
		    &TAILQ_NEXT((elm), field);				\
	else								\
		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
	TAILQ_NEXT((listelm), field) = (elm);				\
	(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);		\
} while (0)

#define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
	TAILQ_NEXT((elm), field) = (listelm);				\
	*(listelm)->field.tqe_prev = (elm);				\
	(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);		\
} while (0)

#define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
	if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)	\
		TAILQ_FIRST((head))->field.tqe_prev =			\
		    &TAILQ_NEXT((elm), field);				\
	else								\
		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
	TAILQ_FIRST((head)) = (elm);					\
	(elm)->field.tqe_prev = &TAILQ_FIRST((head));			\
} while (0)

#define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
	TAILQ_NEXT((elm), field) = NULL;				\
	(elm)->field.tqe_prev = (head)->tqh_last;			\
	*(head)->tqh_last = (elm);					\
	(head)->tqh_last = &TAILQ_NEXT((elm), field);			\
} while (0)

#define	TAILQ_LAST(head, headname)					\
	(*(((struct headname *)((head)->tqh_last))->tqh_last))

#define	TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)

#define	TAILQ_PREV(elm, headname, field)				\
	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))

#define	TAILQ_REMOVE(head, elm, field) do {				\
	if ((TAILQ_NEXT((elm), field)) != NULL)				\
		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
		    (elm)->field.tqe_prev;				\
	else								\
		(head)->tqh_last = (elm)->field.tqe_prev;		\
	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\
} while (0)

#endif 

struct heads my_list;

/*
https://gcc.gnu.org/onlinedocs/gcc-6.2.0/gcc/Common-Function-Attributes.html
*/
__attribute__((constructor(101))) void init101() {
    printf("call %s\r\n", __FUNCTION__);
}

__attribute__((constructor(102))) void init102() {
    printf("call %s, init tailq my_list\r\n", __FUNCTION__);
    TAILQ_INIT(&my_list);
}


__attribute__((destructor)) void dealloc() {
    printf("call dealloc free tail my_list\r\n");
    struct node *ele = TAILQ_FIRST(&my_list);
    while (ele) {
        struct node *prev = ele;
        ele = TAILQ_NEXT(ele, link);
        TAILQ_REMOVE(&my_list, prev, link);
        free(prev);
    }

    printf("After dealloc , list empty %d\r\n", TAILQ_EMPTY(&my_list)?1:0);

}


int main() {
    int i, value;
    struct node *ele = NULL;

 
    for (i = 0; i < 5; i++) {
        printf("enter %d elememt:\r\n", i);
        scanf("%d", &value);

        ele = (struct node *)malloc(sizeof(struct node));
        ele->value = value;
        TAILQ_INSERT_TAIL(&my_list, ele, link);
    }

    printf("TailQ content:\r\n");
    TAILQ_FOREACH(ele, &my_list, link) {
        printf("%d \r\n", ele->value);
    }

    

    printf("After main , list empty %d\r\n", TAILQ_EMPTY(&my_list)?1:0);

    return 0;
}

